package com.pactera.demo.config;

import lombok.extern.slf4j.Slf4j;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;

import java.util.Arrays;

/**
 * <p>
 *
 * </p>
 *
 * @author chang.zhou
 * @version version
 * @date Created in 2020/3/12 19:42
 */
@Slf4j
@Configuration
public class CasSecuredConfiguration {

    @Bean
    public ServiceProperties serviceProperties(ClientConfiguration configuration){
        ServiceProperties serviceProperties = new ServiceProperties();
        serviceProperties.setService(configuration.getClient().getHostUrl()+configuration.getClient().getLoginUrl());
        serviceProperties.setAuthenticateAllArtifacts(true);
        serviceProperties.setSendRenew(false);
        return serviceProperties;
    }

    @Bean
    @Primary
    public CasAuthenticationEntryPoint casAuthenticationEntryPoint(ClientConfiguration configuration,ServiceProperties serviceProperties){
        CasAuthenticationEntryPoint point = new CasAuthenticationEntryPoint();
        point.setLoginUrl(configuration.getCas().getLoginUrl());
        point.setServiceProperties(serviceProperties);
        return point;
    }

    @Bean
    public TicketValidator ticketValidator(ClientConfiguration configuration){
        return new Cas30ServiceTicketValidator(configuration.getCas().getHostUrl());
    }


    @Bean
    public CasAuthenticationProvider casAuthenticationProvider(ServiceProperties serviceProperties,TicketValidator ticketValidator){
        CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
        casAuthenticationProvider.setAuthenticationUserDetailsService((token)->{
            log.info("token.getName={};token.getCredentials={};token.getPrincipal={}", token.getName(),token.getCredentials(),token.getPrincipal());
            return new User(token.getName(), "", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
        });
        casAuthenticationProvider.setServiceProperties(serviceProperties);
        casAuthenticationProvider.setKey("casAuthenticationProviderKey");
        casAuthenticationProvider.setTicketValidator(ticketValidator);

        return casAuthenticationProvider;

    }


    @Bean
    public CasAuthenticationFilter casAuthenticationFilter(ClientConfiguration configuration,AuthenticationManager authenticationManager){
        CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
        casAuthenticationFilter.setFilterProcessesUrl(configuration.getClient().getLoginUrl());
        casAuthenticationFilter.setAuthenticationManager(authenticationManager);
        return casAuthenticationFilter;
    }


    @Bean
    public SingleSignOutFilter singleSignOutFilter(ClientConfiguration configuration){
        SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
        singleSignOutFilter.setCasServerUrlPrefix(configuration.getCas().getHostUrl());
        singleSignOutFilter.setIgnoreInitConfiguration(true);
        return singleSignOutFilter;
    }

    @Bean
    public LogoutFilter logoutFilter(ClientConfiguration configuration){
        LogoutFilter logoutFilter = new LogoutFilter(configuration.getCas().getLogoutUrl(),securityContextLogoutHandler());
        logoutFilter.setFilterProcessesUrl(configuration.getClient().getLogoutUrl());
        return logoutFilter;
    }

    @Bean
    public AuthenticationManager authenticationManager(CasAuthenticationProvider authenticationProvider){
        return new ProviderManager(Arrays.asList(authenticationProvider));
    }

    @Bean
    public SecurityContextLogoutHandler securityContextLogoutHandler() {
        return new SecurityContextLogoutHandler();
    }
}
